package com.gg.communication.communication.udp.server;

import com.gg.communication.communication.BaseCommunication;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketAddress;
import java.net.SocketException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

/**
 * @author sakura
 * @since 2025-06-16
 */

public class UdpServer extends BaseCommunication {
    private DatagramSocket socket;
    private final Set<SocketAddress> clients = Collections.synchronizedSet(new HashSet<>());
    private volatile boolean running = false;


    public static BaseCommunication initServer() {
        if (getInstance() == null)
            getInstance(new UdpServer());
        return getInstance();
    }

    @Override
    protected void startCommunication() throws SocketException {
        socket = new DatagramSocket(getPort());
        System.out.println("UDP server started on port " + getPort());
    }

    @Override
    public void doCommunicationSend(byte[] msg, String host, int port) throws IOException {
        synchronized (clients) {
            for (SocketAddress client : clients) {
                try {
                    DatagramPacket packet = new DatagramPacket(msg, msg.length, client);
                    socket.send(packet);
                } catch (IOException e) {
                    e.printStackTrace();
                    System.err.println("Failed to send to " + client + ": " + e.getMessage());
                }
            }
        }
    }

    @Override
    public byte[] doReceive() throws Exception {
        byte[] buffer = new byte[4096];
        DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
        socket.receive(packet);
        System.out.println("port" + packet.getPort() + " receive from " + packet.getSocketAddress());
        clients.add(packet.getSocketAddress());
        byte[] responseData = new byte[packet.getLength()];
        System.arraycopy(packet.getData(), packet.getOffset(), responseData, 0, packet.getLength());
        //if (receiveListener != null) {
        //    receiveListener.receive(responseData);
        //}
        return responseData;
    }

    @Override
    public void close() throws IOException {
        if (socket != null && !socket.isClosed()) {
            socket.close();
        }
        super.close();
    }
}
